package com.example.service;

import com.example.entity.University;
import com.example.mapper.UniversityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import weka.classifiers.functions.SMO;
import weka.classifiers.functions.SMOreg;
import weka.classifiers.functions.supportVector.PolyKernel;
import weka.classifiers.functions.supportVector.RBFKernel;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;


import java.util.*;

@Service
public class SchoolPredictionService {
    @Autowired
    private UniversityRepository universityRepository;

    /**
     * 根据给定的学校和专业名称预测分数线。
     *
     * @param school 学校名称
     * @param major 专业名称
     * @return 预测的分数线
     * @throws Exception 当预测过程中出现问题时抛出
     */
    public double predictScore(String school, String major) throws Exception {
        // 从数据库获取特定学校和专业的历史数据
        List<University> universities = universityRepository.findBySchoolAndMajor(school, major);

        // 准备用于模型训练的数据集
        Instances dataset = prepareDataset(universities);

        // 将数据集的最后一个属性设置为目标变量（即要预测的分数线）
        dataset.setClassIndex(dataset.numAttributes() - 1);

        // 使用SMOreg算法创建回归模型
        SMOreg smoreg = new SMOreg();
        smoreg.setC(2.0);

        smoreg.buildClassifier(dataset);

        // 创建一个预测实例，用于预测
        Instance predictInstance = createPredictInstance(universities, dataset);

        // 返回预测结果
        return smoreg.classifyInstance(predictInstance);
    }


    /**
     * 评估模型的拟合度，返回均方误差（MSE）和决定系数（R²）。
     *
     * @param school 学校名称
     * @param major 专业名称
     * @return 包含MSE和R²的Map
     * @throws Exception 当评估过程中出现问题时抛出
     */
    public Map<String, Double> evaluateModel(String school, String major) throws Exception {
        List<University> universities = universityRepository.findBySchoolAndMajor(school, major);
        Instances dataset = prepareDataset(universities);
        dataset.setClassIndex(dataset.numAttributes() - 1);

        SMOreg smoreg = new SMOreg();

        smoreg.buildClassifier(dataset);

        double mse = 0;
        double ssTotal = 0;
        double mean = dataset.meanOrMode(dataset.classIndex());

        for (int i = 0; i < dataset.numInstances(); i++) {
            Instance instance = dataset.instance(i);
            double actual = instance.classValue();
            double predicted = smoreg.classifyInstance(instance);
            mse += Math.pow(actual - predicted, 2);
            ssTotal += Math.pow(actual - mean, 2);
        }

        mse /= dataset.numInstances();
        double rSquared = 1 - (mse / (ssTotal / dataset.numInstances()));

        Map<String, Double> results = new HashMap<>();
        results.put("MSE", mse);
        results.put("R2", rSquared);

        // 打印评估结果到控制台
        System.out.println("Model evaluation for school: " + school + ", major: " + major);
        System.out.println("MSE: " + mse);
        System.out.println("R-squared: " + rSquared);

        return results;
    }

    /**
     * 准备数据集，包括特征和目标变量。
     *
     * @param universities 学校历史数据列表
     * @return 构建好的数据集
     */
    private Instances prepareDataset(List<University> universities) {
        // 定义数据集的属性
        ArrayList<Attribute> attributes = new ArrayList<>();
        attributes.add(new Attribute("bbl")); // 报录比
        attributes.add(new Attribute("number")); // 招生人数
        attributes.add(new Attribute("methodNumeric")); // 考试形式的数值表示（统考=1，自命题=0）
        attributes.add(new Attribute("line")); // 分数线

        // 创建数据集实例，初始容量为0
        Instances dataset = new Instances("UniversityData", attributes, 0);

        // 遍历历史数据，将其转换为数据集的实例
        for (University uni : universities) {
            double[] vals = new double[dataset.numAttributes()];
            vals[0] = uni.getBbl();
            vals[1] = uni.getNumber();
            vals[2] = "统考".equals(uni.getMethod()) ? 1.0 : 0.0;
            vals[3] = uni.getLine();

            dataset.add(new DenseInstance(1.0, vals));
        }

        return dataset;
    }

    /**
     * 创建一个用于预测的实例，它不包含目标变量的值。
     *
     * @param universities 学校历史数据列表
     * @param dataset 数据集
     * @return 预测实例
     */
    private Instance createPredictInstance(List<University> universities, Instances dataset) {
        // 获取最近一年的数据作为预测基础
        University lastYear = universities.get(universities.size() - 1);

        double[] vals = new double[dataset.numAttributes()];
        vals[0] = lastYear.getBbl();
        vals[1] = lastYear.getNumber();
        vals[2] = "统考".equals(lastYear.getMethod()) ? 1.0 : 0.0;

        // 创建实例并设置所属的数据集
        Instance instance = new DenseInstance(1.0, vals);
        instance.setDataset(dataset);

        return instance;
    }

}

//@Service
//public class SchoolPredictionService {
//    @Autowired
//    private UniversityRepository universityRepository;
//
//
//    public double predictScore(String school, String major) throws Exception {
//        List<University> universities = universityRepository.findBySchoolAndMajor(school, major);
//        Instances dataset = prepareDataset(universities);
//
//        // 设置最后一个属性为目标变量
//        dataset.setClassIndex(dataset.numAttributes() - 1);
//
//        SMOreg smoreg = new SMOreg();
//        smoreg.buildClassifier(dataset);
//
//        Instance predictInstance = createPredictInstance(universities, dataset);
//        return smoreg.classifyInstance(predictInstance);
//    }
//
//    private Instances prepareDataset(List<University> universities) {
//        ArrayList<Attribute> attributes = new ArrayList<>();
//        attributes.add(new Attribute("bbl"));
//        attributes.add(new Attribute("number"));
//        attributes.add(new Attribute("methodNumeric"));
//        attributes.add(new Attribute("line"));
//
//        Instances dataset = new Instances("UniversityData", attributes, 0);
//
//        for (University uni : universities) {
//            double[] vals = new double[dataset.numAttributes()];
//            vals[0] = uni.getBbl();
//            vals[1] = uni.getNumber();
//            vals[2] = "统考".equals(uni.getMethod()) ? 1.0 : 0.0;
//            vals[3] = uni.getLine();
//
//            dataset.add(new DenseInstance(1.0, vals));
//        }
//
//        return dataset;
//    }
//
//    private Instance createPredictInstance(List<University> universities, Instances dataset) {
//        University lastYear = universities.get(universities.size() - 1);
//
//        double[] vals = new double[dataset.numAttributes()];
//        vals[0] = lastYear.getBbl();
//        vals[1] = lastYear.getNumber();
//        vals[2] = "统考".equals(lastYear.getMethod()) ? 1.0 : 0.0;
//
//        Instance instance = new DenseInstance(1.0, vals);
//        instance.setDataset(dataset);
//
//        return instance;
//    }
//
//}
